import json
import jsonschema
from typing import List, Dict, Any, Optional, Union
from datetime import datetime
from enum import Enum
import uuid
import copy
from pathlib import Path

from ..models.audit_models import AuditStandard, AuditRule, RuleCondition, RulePriority
from ..utils.logger import get_logger
from .audit_rules import BaseRule, RuleCheckResult, RuleStatus

logger = get_logger(__name__)


class StandardType(str, Enum):
    """审核标准类型枚举."""
    DEFAULT = "default"
    CUSTOM = "custom"
    TEMPLATE = "template"


class CustomRule(BaseRule):
    """自定义规则实现."""
    
    def __init__(self, rule_config: Dict[str, Any]):
        super().__init__(
            rule_id=rule_config.get("rule_id", str(uuid.uuid4())),
            name=rule_config.get("name", "自定义规则"),
            priority=RulePriority(rule_config.get("priority", "medium")),
            weight=rule_config.get("weight", 1.0),
            is_blocking=rule_config.get("is_blocking", False)
        )
        
        self.conditions = [RuleCondition(**cond) for cond in rule_config.get("conditions", [])]
        self.condition_logic = rule_config.get("condition_logic", "AND")
        self.action = rule_config.get("action", "score")
        self.score_impact = rule_config.get("score_impact", 0)
        self.message_template = rule_config.get("message", "自定义规则检查")
    
    def check(self, request) -> RuleCheckResult:
        """执行自定义规则检查."""
        start_time = datetime.now()
        
        try:
            condition_results = []
            
            for condition in self.conditions:
                result = self._evaluate_condition(condition, request)
                condition_results.append(result)
            
            # 根据条件逻辑组合结果
            if self.condition_logic.upper() == "AND":
                final_result = all(condition_results)
            else:  # OR
                final_result = any(condition_results)
            
            execution_time = (datetime.now() - start_time).total_seconds() * 1000
            
            if final_result:
                status = RuleStatus.PASS if self.score_impact >= 0 else RuleStatus.FAIL
                message = f"{self.message_template} - 通过"
            else:
                status = RuleStatus.FAIL if self.score_impact < 0 else RuleStatus.WARNING
                message = f"{self.message_template} - 未通过"
            
            return RuleCheckResult(
                status=status,
                score_impact=self.score_impact if final_result else -abs(self.score_impact),
                message=message,
                details={
                    "conditions_met": final_result,
                    "condition_results": condition_results,
                    "logic": self.condition_logic
                },
                execution_time_ms=execution_time
            )
            
        except Exception as e:
            execution_time = (datetime.now() - start_time).total_seconds() * 1000
            logger.error(f"自定义规则执行异常 {self.name}: {str(e)}")
            return RuleCheckResult(
                status=RuleStatus.WARNING,
                score_impact=-5,
                message=f"规则执行异常: {str(e)}",
                execution_time_ms=execution_time
            )
    
    def _evaluate_condition(self, condition: RuleCondition, request) -> bool:
        """评估单个条件."""
        try:
            # 获取字段值
            field_value = self._get_field_value(request, condition.field_name)
            target_value = condition.value
            operator = condition.operator.lower()
            
            # 执行比较操作
            if operator == "eq":
                return field_value == target_value
            elif operator == "ne":
                return field_value != target_value
            elif operator == "gt":
                return float(field_value) > float(target_value)
            elif operator == "gte":
                return float(field_value) >= float(target_value)
            elif operator == "lt":
                return float(field_value) < float(target_value)
            elif operator == "lte":
                return float(field_value) <= float(target_value)
            elif operator == "in":
                return field_value in target_value
            elif operator == "not_in":
                return field_value not in target_value
            elif operator == "contains":
                return str(target_value).lower() in str(field_value).lower()
            elif operator == "not_contains":
                return str(target_value).lower() not in str(field_value).lower()
            elif operator == "regex":
                import re
                return bool(re.search(str(target_value), str(field_value)))
            else:
                logger.warning(f"未知操作符: {operator}")
                return False
                
        except Exception as e:
            logger.error(f"条件评估异常: {str(e)}")
            return False
    
    def _get_field_value(self, request, field_name: str):
        """获取请求对象中的字段值."""
        # 支持点号分隔的嵌套字段访问
        fields = field_name.split(".")
        value = request
        
        for field in fields:
            if hasattr(value, field):
                value = getattr(value, field)
            elif isinstance(value, dict) and field in value:
                value = value[field]
            else:
                return None
        
        return value


class StandardParser:
    """审核标准解析器."""
    
    def __init__(self):
        self.json_schema = self._get_standard_schema()
    
    def _get_standard_schema(self) -> Dict[str, Any]:
        """获取审核标准的JSON Schema."""
        return {
            "type": "object",
            "required": ["name", "version", "rules"],
            "properties": {
                "name": {"type": "string", "minLength": 1, "maxLength": 100},
                "description": {"type": "string", "maxLength": 1000},
                "version": {"type": "string", "pattern": r"^\d+\.\d+$"},
                "rules": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "required": ["name", "conditions", "action"],
                        "properties": {
                            "rule_id": {"type": "string"},
                            "name": {"type": "string", "minLength": 1, "maxLength": 100},
                            "description": {"type": "string", "maxLength": 500},
                            "conditions": {
                                "type": "array",
                                "minItems": 1,
                                "items": {
                                    "type": "object",
                                    "required": ["field_name", "operator", "value"],
                                    "properties": {
                                        "field_name": {"type": "string"},
                                        "operator": {"type": "string", "enum": [
                                            "eq", "ne", "gt", "gte", "lt", "lte",
                                            "in", "not_in", "contains", "not_contains", "regex"
                                        ]},
                                        "value": {},
                                        "weight": {"type": "number", "minimum": 0, "maximum": 1}
                                    }
                                }
                            },
                            "condition_logic": {"type": "string", "enum": ["AND", "OR"]},
                            "action": {"type": "string", "enum": ["approve", "reject", "flag", "score"]},
                            "score_impact": {"type": "number", "minimum": -100, "maximum": 100},
                            "message": {"type": "string"},
                            "priority": {"type": "string", "enum": ["low", "medium", "high", "critical"]},
                            "weight": {"type": "number", "minimum": 0, "maximum": 1},
                            "is_blocking": {"type": "boolean"},
                            "is_active": {"type": "boolean"}
                        }
                    }
                },
                "auto_approve_threshold": {"type": "number", "minimum": 0, "maximum": 100},
                "auto_reject_threshold": {"type": "number", "minimum": 0, "maximum": 100},
                "manual_review_threshold": {"type": "number", "minimum": 0, "maximum": 100},
                "applicable_contexts": {"type": "array", "items": {"type": "string"}},
                "excluded_contexts": {"type": "array", "items": {"type": "string"}}
            }
        }
    
    def validate_standard(self, standard_data: Dict[str, Any]) -> bool:
        """验证审核标准数据格式."""
        try:
            jsonschema.validate(standard_data, self.json_schema)
            
            # 额外的业务逻辑验证
            auto_approve = standard_data.get("auto_approve_threshold", 80)
            auto_reject = standard_data.get("auto_reject_threshold", 30)
            
            if auto_reject >= auto_approve:
                raise ValueError("自动拒绝阈值必须小于自动通过阈值")
            
            return True
            
        except jsonschema.ValidationError as e:
            logger.error(f"标准格式验证失败: {e.message}")
            raise ValueError(f"标准格式验证失败: {e.message}")
        except Exception as e:
            logger.error(f"标准验证异常: {str(e)}")
            raise ValueError(f"标准验证异常: {str(e)}")
    
    def parse_standard(self, standard_data: Dict[str, Any]) -> AuditStandard:
        """解析JSON数据为审核标准对象."""
        # 先验证格式
        self.validate_standard(standard_data)
        
        # 解析规则
        rules = []
        for rule_data in standard_data.get("rules", []):
            # 为每个条件创建RuleCondition对象
            conditions = []
            for cond_data in rule_data.get("conditions", []):
                condition = RuleCondition(
                    field_name=cond_data["field_name"],
                    operator=cond_data["operator"],
                    value=cond_data["value"],
                    weight=cond_data.get("weight", 1.0)
                )
                conditions.append(condition)
            
            # 创建AuditRule对象
            rule = AuditRule(
                rule_id=rule_data.get("rule_id", str(uuid.uuid4())),
                name=rule_data["name"],
                description=rule_data.get("description"),
                conditions=conditions,
                condition_logic=rule_data.get("condition_logic", "AND"),
                action=rule_data["action"],
                score_impact=rule_data.get("score_impact", 0),
                message=rule_data.get("message"),
                priority=RulePriority(rule_data.get("priority", "medium")),
                is_active=rule_data.get("is_active", True),
                is_blocking=rule_data.get("is_blocking", False)
            )
            rules.append(rule)
        
        # 创建AuditStandard对象
        standard = AuditStandard(
            name=standard_data["name"],
            description=standard_data.get("description"),
            version=standard_data["version"],
            rules=rules,
            auto_approve_threshold=standard_data.get("auto_approve_threshold", 80.0),
            auto_reject_threshold=standard_data.get("auto_reject_threshold", 30.0),
            manual_review_threshold=standard_data.get("manual_review_threshold", 50.0),
            applicable_contexts=standard_data.get("applicable_contexts"),
            excluded_contexts=standard_data.get("excluded_contexts"),
            is_active=standard_data.get("is_active", True)
        )
        
        return standard
    
    def export_standard(self, standard: AuditStandard) -> Dict[str, Any]:
        """将审核标准对象导出为JSON格式."""
        rules_data = []
        for rule in standard.rules:
            conditions_data = []
            for condition in rule.conditions:
                conditions_data.append({
                    "field_name": condition.field_name,
                    "operator": condition.operator,
                    "value": condition.value,
                    "weight": condition.weight
                })
            
            rule_data = {
                "rule_id": rule.rule_id,
                "name": rule.name,
                "description": rule.description,
                "conditions": conditions_data,
                "condition_logic": rule.condition_logic,
                "action": rule.action,
                "score_impact": rule.score_impact,
                "message": rule.message,
                "priority": rule.priority.value,
                "is_active": rule.is_active,
                "is_blocking": rule.is_blocking
            }
            rules_data.append(rule_data)
        
        return {
            "name": standard.name,
            "description": standard.description,
            "version": standard.version,
            "rules": rules_data,
            "auto_approve_threshold": standard.auto_approve_threshold,
            "auto_reject_threshold": standard.auto_reject_threshold,
            "manual_review_threshold": standard.manual_review_threshold,
            "applicable_contexts": standard.applicable_contexts,
            "excluded_contexts": standard.excluded_contexts,
            "is_active": standard.is_active,
            "created_at": standard.created_at.isoformat(),
            "updated_at": standard.updated_at.isoformat() if standard.updated_at else None
        }


class StandardManager:
    """审核标准管理器."""
    
    def __init__(self, storage_path: str = "data/audit_standards/"):
        self.storage_path = Path(storage_path)
        self.storage_path.mkdir(parents=True, exist_ok=True)
        self.parser = StandardParser()
        self.standards_cache: Dict[str, AuditStandard] = {}
        self._load_templates()
    
    def _load_templates(self):
        """加载预定义模板."""
        templates = self._get_predefined_templates()
        for template_name, template_data in templates.items():
            try:
                standard = self.parser.parse_standard(template_data)
                standard.is_default = True
                self.standards_cache[standard.standard_id] = standard
                logger.info(f"加载模板: {template_name}")
            except Exception as e:
                logger.error(f"加载模板失败 {template_name}: {str(e)}")
    
    def _get_predefined_templates(self) -> Dict[str, Dict[str, Any]]:
        """获取预定义审核标准模板."""
        return {
            "strict_mode": {
                "name": "严格审核模式",
                "description": "适用于重要场所和活动的严格审核标准",
                "version": "1.0",
                "auto_approve_threshold": 90.0,
                "auto_reject_threshold": 50.0,
                "manual_review_threshold": 70.0,
                "rules": [
                    {
                        "name": "申请人资格严格检查",
                        "description": "仅允许教师和管理员申请",
                        "conditions": [
                            {
                                "field_name": "applicant_info.type",
                                "operator": "in",
                                "value": ["teacher", "admin"],
                                "weight": 1.0
                            }
                        ],
                        "action": "score",
                        "score_impact": 20,
                        "message": "申请人资格符合严格要求",
                        "priority": "high",
                        "is_blocking": True
                    },
                    {
                        "name": "使用时长限制",
                        "description": "限制单次使用不超过4小时",
                        "conditions": [
                            {
                                "field_name": "duration_hours",
                                "operator": "lte",
                                "value": 4,
                                "weight": 1.0
                            }
                        ],
                        "action": "score",
                        "score_impact": 15,
                        "message": "使用时长符合限制",
                        "priority": "medium"
                    },
                    {
                        "name": "提前申请时间检查",
                        "description": "必须提前至少3天申请",
                        "conditions": [
                            {
                                "field_name": "advance_days",
                                "operator": "gte",
                                "value": 3,
                                "weight": 1.0
                            }
                        ],
                        "action": "score",
                        "score_impact": 10,
                        "message": "申请时间符合要求",
                        "priority": "medium"
                    }
                ]
            },
            "lenient_mode": {
                "name": "宽松审核模式",
                "description": "适用于一般日常活动的宽松审核标准",
                "version": "1.0",
                "auto_approve_threshold": 60.0,
                "auto_reject_threshold": 20.0,
                "manual_review_threshold": 40.0,
                "rules": [
                    {
                        "name": "基础资格检查",
                        "description": "允许所有注册用户申请",
                        "conditions": [
                            {
                                "field_name": "applicant_info.type",
                                "operator": "in",
                                "value": ["teacher", "admin", "student"],
                                "weight": 1.0
                            }
                        ],
                        "action": "score",
                        "score_impact": 15,
                        "message": "申请人资格验证通过",
                        "priority": "medium"
                    },
                    {
                        "name": "合理使用时长",
                        "description": "单次使用不超过8小时",
                        "conditions": [
                            {
                                "field_name": "duration_hours",
                                "operator": "lte",
                                "value": 8,
                                "weight": 1.0
                            }
                        ],
                        "action": "score",
                        "score_impact": 10,
                        "message": "使用时长合理",
                        "priority": "low"
                    }
                ]
            },
            "special_event_mode": {
                "name": "特殊活动模式",
                "description": "适用于大型活动和特殊场合的审核标准",
                "version": "1.0",
                "auto_approve_threshold": 75.0,
                "auto_reject_threshold": 40.0,
                "manual_review_threshold": 60.0,
                "rules": [
                    {
                        "name": "活动规模检查",
                        "description": "大型活动需要特别审核",
                        "conditions": [
                            {
                                "field_name": "participants_count",
                                "operator": "gte",
                                "value": 100,
                                "weight": 1.0
                            }
                        ],
                        "action": "flag",
                        "score_impact": 0,
                        "message": "大型活动，需要额外审核",
                        "priority": "high"
                    },
                    {
                        "name": "特殊设备需求",
                        "description": "检查是否有特殊设备需求",
                        "conditions": [
                            {
                                "field_name": "equipment_needs",
                                "operator": "contains",
                                "value": "音响",
                                "weight": 0.8
                            }
                        ],
                        "action": "score",
                        "score_impact": 5,
                        "message": "特殊设备需求已记录",
                        "priority": "medium"
                    }
                ]
            }
        }
    
    def create_standard(self, standard_data: Dict[str, Any]) -> AuditStandard:
        """创建新的审核标准."""
        try:
            standard = self.parser.parse_standard(standard_data)
            
            # 保存到文件
            file_path = self.storage_path / f"{standard.standard_id}.json"
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(self.parser.export_standard(standard), f, 
                         ensure_ascii=False, indent=2)
            
            # 缓存
            self.standards_cache[standard.standard_id] = standard
            
            logger.info(f"创建审核标准: {standard.name}")
            return standard
            
        except Exception as e:
            logger.error(f"创建审核标准失败: {str(e)}")
            raise
    
    def get_standard(self, standard_id: str) -> Optional[AuditStandard]:
        """获取指定审核标准."""
        if standard_id in self.standards_cache:
            return self.standards_cache[standard_id]
        
        # 尝试从文件加载
        try:
            file_path = self.storage_path / f"{standard_id}.json"
            if file_path.exists():
                with open(file_path, 'r', encoding='utf-8') as f:
                    standard_data = json.load(f)
                
                standard = self.parser.parse_standard(standard_data)
                self.standards_cache[standard_id] = standard
                return standard
                
        except Exception as e:
            logger.error(f"加载审核标准失败 {standard_id}: {str(e)}")
        
        return None
    
    def update_standard(self, standard_id: str, updates: Dict[str, Any]) -> AuditStandard:
        """更新审核标准."""
        standard = self.get_standard(standard_id)
        if not standard:
            raise ValueError(f"审核标准不存在: {standard_id}")
        
        # 导出当前标准数据
        current_data = self.parser.export_standard(standard)
        
        # 应用更新
        current_data.update(updates)
        current_data["updated_at"] = datetime.now().isoformat()
        
        # 重新解析和验证
        updated_standard = self.parser.parse_standard(current_data)
        updated_standard.standard_id = standard_id  # 保持ID不变
        
        # 保存到文件
        file_path = self.storage_path / f"{standard_id}.json"
        with open(file_path, 'w', encoding='utf-8') as f:
            json.dump(self.parser.export_standard(updated_standard), f,
                     ensure_ascii=False, indent=2)
        
        # 更新缓存
        self.standards_cache[standard_id] = updated_standard
        
        logger.info(f"更新审核标准: {updated_standard.name}")
        return updated_standard
    
    def delete_standard(self, standard_id: str) -> bool:
        """删除审核标准."""
        try:
            # 检查是否为默认模板
            standard = self.get_standard(standard_id)
            if standard and standard.is_default:
                raise ValueError("不能删除预定义模板")
            
            # 删除文件
            file_path = self.storage_path / f"{standard_id}.json"
            if file_path.exists():
                file_path.unlink()
            
            # 删除缓存
            if standard_id in self.standards_cache:
                del self.standards_cache[standard_id]
            
            logger.info(f"删除审核标准: {standard_id}")
            return True
            
        except Exception as e:
            logger.error(f"删除审核标准失败 {standard_id}: {str(e)}")
            raise
    
    def list_standards(self, include_inactive: bool = False) -> List[AuditStandard]:
        """列出所有审核标准."""
        standards = []
        
        # 加载所有文件中的标准
        for file_path in self.storage_path.glob("*.json"):
            try:
                standard_id = file_path.stem
                standard = self.get_standard(standard_id)
                if standard and (include_inactive or standard.is_active):
                    standards.append(standard)
            except Exception as e:
                logger.error(f"加载标准文件失败 {file_path}: {str(e)}")
        
        # 添加缓存中的模板标准
        for standard in self.standards_cache.values():
            if standard.is_default and (include_inactive or standard.is_active):
                if standard not in standards:
                    standards.append(standard)
        
        return sorted(standards, key=lambda x: x.name)
    
    def duplicate_standard(self, source_id: str, new_name: str) -> AuditStandard:
        """复制审核标准."""
        source_standard = self.get_standard(source_id)
        if not source_standard:
            raise ValueError(f"源审核标准不存在: {source_id}")
        
        # 导出源标准数据
        standard_data = self.parser.export_standard(source_standard)
        
        # 修改名称和ID
        standard_data["name"] = new_name
        standard_data["version"] = "1.0"
        del standard_data["created_at"]
        if "updated_at" in standard_data:
            del standard_data["updated_at"]
        
        # 创建新标准
        return self.create_standard(standard_data)
    
    def export_standards(self, standard_ids: List[str] = None) -> Dict[str, Dict[str, Any]]:
        """导出审核标准为JSON格式."""
        result = {}
        
        if standard_ids is None:
            standards = self.list_standards(include_inactive=True)
            standard_ids = [s.standard_id for s in standards]
        
        for standard_id in standard_ids:
            standard = self.get_standard(standard_id)
            if standard:
                result[standard_id] = self.parser.export_standard(standard)
        
        return result
    
    def import_standards(self, standards_data: Dict[str, Dict[str, Any]]) -> List[str]:
        """导入审核标准."""
        imported_ids = []
        
        for standard_id, standard_data in standards_data.items():
            try:
                standard = self.create_standard(standard_data)
                imported_ids.append(standard.standard_id)
                logger.info(f"导入审核标准: {standard.name}")
            except Exception as e:
                logger.error(f"导入标准失败 {standard_id}: {str(e)}")
        
        return imported_ids